import socket
import threading
import json
import random

# 服务端配置
HOST = '127.0.0.1'  # 本地地址
PORT = 65432        # 端口号

# 游戏状态
clients = []  # 存储客户端连接
game_state = {
    'players': [],  # 玩家列表
    'current_player': 0,  # 当前玩家
    'game_started': False,  # 游戏是否开始
    'chess_positions': [],  # 棋子位置
    'dice_value': 6,  # 骰子点数
    'game_round': 0   # 游戏轮数
}


class FlyingChessServer:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.server_socket = None
        self.clients = []
        self.game_state = {
            'players': [],
            'current_player': 0,
            'game_started': False,
            'chess_positions': self.initialize_chess_positions(),
            'dice_value': 6,
            'game_round': 0
        }
        
    def initialize_chess_positions(self):
        """
        初始化棋子位置
        根据main.py中的初始位置设置
        """
        # 棋子初始状态 [x, y, 是否起飞, 是否到达终点]
        chess = [
            # 红色棋子
            [[46.2, 407.4 + 100, False, False],
             [46.2, 447.4 + 100, False, False],
             [86.2, 407.4 + 100, False, False],
             [86.2, 447.4 + 100, False, False]],
            # 黄色棋子
            [[46.2, 40 + 100, False, False],
             [46.2, 80 + 100, False, False],
             [86.2, 40 + 100, False, False],
             [86.2, 80 + 100, False, False]],
            # 蓝色棋子
            [[454.4, 40 + 100, False, False],
             [454.4, 80 + 100, False, False],
             [414.4, 40 + 100, False, False],
             [414.4, 80 + 100, False, False]],
            # 绿色棋子
            [[455, 447.4 + 100, False, False],
             [455, 407.4 + 100, False, False],
             [415, 447.4 + 100, False, False],
             [415, 407.4 + 100, False, False]]
        ]
        return chess
    
    def start_server(self):
        """启动服务器"""
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind((self.host, self.port))
        self.server_socket.listen(4)  # 最多支持4个玩家
        print(f"飞行棋服务器启动，监听 {self.host}:{self.port}")
        
        try:
            while True:
                client_socket, address = self.server_socket.accept()
                print(f"新客户端连接: {address}")
                
                # 创建新线程处理客户端
                client_thread = threading.Thread(
                    target=self.handle_client,
                    args=(client_socket, address)
                )
                client_thread.daemon = True
                client_thread.start()
                
        except KeyboardInterrupt:
            print("\n服务器关闭")
        finally:
            self.server_socket.close()

    def handle_client(self, client_socket, address):
        """处理客户端连接"""
        # 添加客户端到列表
        player_id = len(self.game_state['players'])
        self.clients.append({
            'socket': client_socket,
            'address': address,
            'player_id': player_id
        })

        # 添加玩家到游戏状态
        self.game_state['players'].append({
            'id': player_id,
            'address': address,
            'ready': False
        })

        # 发送玩家ID
        self.send_message(client_socket, {
            'type': 'assign_player_id',
            'player_id': player_id
        })

        # 广播玩家加入消息
        self.broadcast_message({
            'type': 'player_joined',
            'player_id': player_id,
            'total_players': len(self.game_state['players'])
        })

        try:
            while True:
                # 接收客户端消息
                data = client_socket.recv(1024).decode('utf-8')
                if not data:
                    break

                try:
                    message = json.loads(data)
                    self.process_message(message, player_id)
                except json.JSONDecodeError:
                    print(f"无效的JSON数据: {data}")

        except ConnectionResetError:
            print(f"客户端 {address} 断开连接")
        finally:
            # 移除客户端
            self.remove_client(client_socket)

    def remove_client(self, client_socket):
        """从客户端列表和玩家列表中移除客户端"""
        # 查找要移除的客户端
        client_to_remove = None
        for client in self.clients:
            if client['socket'] == client_socket:
                client_to_remove = client
                break

        if client_to_remove:
            player_id = client_to_remove['player_id']
            # 从客户端列表中移除
            self.clients = [c for c in self.clients if c['socket'] != client_socket]

        # 从玩家列表中移除该玩家
        if not self.game_state['game_started']:
            if player_id < len(self.game_state['players']):
                # 移除该玩家
                self.game_state['players'].pop(player_id)

                # 更新后续玩家的player_id
                for i, client in enumerate(self.clients):
                    if client['player_id'] > player_id:
                        client['player_id'] = i

                # 通知所有客户端玩家列表已更新
                self.broadcast_message({
                    'type': 'player_left',
                    'player_id': player_id,
                    'total_players': len(self.game_state['players'])
                })

        # 关闭socket连接
        try:
            client_socket.close()
        except Exception as e:
            print(f"客户端已移除，剩余玩家数: {len(self.game_state['players'])}")

    def process_message(self, message, player_id):
        """处理客户端消息"""
        try:
            msg_type = message.get('type')

            if msg_type == 'player_ready':
                # 玩家准备就绪
                if player_id < len(self.game_state['players']):
                    self.game_state['players'][player_id]['ready'] = True
                    print(f"玩家 {player_id} 准备就绪")

                    # 检查是否所有玩家都准备就绪 (需要至少4个玩家，且所有已连接玩家都准备就绪)
                    ready_players = sum(1 for player in self.game_state['players'] if player['ready'])
                    total_players = len(self.game_state['players'])
                    if total_players == 4 and ready_players == total_players:
                        self.start_game()

            elif msg_type == 'roll_dice':
                # 玩家掷骰子
                if player_id == self.game_state['current_player']:
                    dice_value = random.randint(1, 6)
                    self.game_state['dice_value'] = dice_value
                    self.game_state['game_round'] += 1
                    current_chess = message.get('chess')
                    # 遍历当前玩家的所有棋子的状态，若点数为不为6点且无已起飞的棋子，则跳过移动棋子阶段，到下一玩家回合
                    if dice_value != 6:
                        for chess in current_chess:
                            if chess[2]:    # 棋子已起飞
                                current_player = player_id
                                stage = 1
                                break
                        else:
                            current_player = (player_id + 1) % 4
                            stage = 0
                    else:
                        current_player = player_id
                        stage = 1
                    self.game_state['current_player'] = current_player
                    # 广播骰子结果
                    self.broadcast_message({
                        'type': 'dice_result',
                        'player_id': player_id,
                        'dice_value': dice_value,
                        'current_player': current_player,
                        'stage': stage
                    })

            elif msg_type == 'move_chess':
                # 玩家移动棋子
                chess_id = message.get('chess_id')

                if player_id == self.game_state['current_player']:
                    # 广播棋子移动
                    self.broadcast_message({
                        'type': 'chess_moved',
                        'player_id': player_id,
                        'chess_id': chess_id,
                        'dice_value': self.game_state['dice_value'],
                        'chess_positions': self.game_state['chess_positions']
                    })

                    # 如果不是6点，切换到下一个玩家
                    if self.game_state['dice_value'] != 6:
                        self.game_state['current_player'] = (self.game_state['current_player'] + 1) % len(
                            self.game_state['players'])
                        # 广播玩家切换消息
                        self.broadcast_message({
                            'type': 'player_switched',
                            'current_player': self.game_state['current_player'],
                            'stage': 0
                        })
            else:
                print(f"未知消息类型: {msg_type}")
        except Exception as e:
            print(f"处理消息时出错: {e}")
            import traceback
            traceback.print_exc()
    
    def start_game(self):
        """开始游戏"""
        self.game_state['game_started'] = True
        self.game_state['current_player'] = 0
        
        self.broadcast_message({
            'type': 'game_start',
            'initial_state': self.game_state
        })
        
        print("游戏开始！")
    
    def send_message(self, client_socket, message):
        """发送消息到指定客户端"""
        try:
            client_socket.send(json.dumps(message).encode('utf-8'))
        except Exception as e:
            print(f"发送消息失败: {e}")
    
    def broadcast_message(self, message):
        """广播消息到所有客户端"""
        disconnected_clients = []
        
        for client in self.clients:
            try:
                client['socket'].send(json.dumps(message).encode('utf-8'))
            except Exception as e:
                print(f"向客户端 {client['address']} 广播消息失败: {e}")
                disconnected_clients.append(client)
        
        # 移除断开连接的客户端
        for client in disconnected_clients:
            self.clients.remove(client)


if __name__ == "__main__":
    server = FlyingChessServer(HOST, PORT)
    server.start_server()
